home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / hdlc.c < prev    next >
C/C++ Source or Header  |  1994-09-24  |  10KB  |  377 lines

  1. /*
  2.  *         PPP High Level Link Control (HDLC) Module
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan, Inc.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  *    TODO:
  21.  */
  22. #include "fsm.h"
  23. #include "hdlc.h"
  24. #include "lcpproto.h"
  25. #include "lcp.h"
  26. #include "lqr.h"
  27.  
  28. struct hdlcstat {
  29.   int    badfcs;
  30.   int    badaddr;
  31.   int    badcommand;
  32.   int    unknownproto;
  33. } HdlcStat;
  34.  
  35. static int ifOutPackets, ifOutOctets, ifOutLQRs;
  36. static int ifInPackets, ifInOctets;
  37.  
  38. struct protostat {
  39.   u_short number;
  40.   char *name;
  41.   u_long in_count;
  42.   u_long out_count;
  43. } ProtocolStat[] = {
  44.   { PROTO_IP,        "IP" },
  45.   { PROTO_VJUNCOMP,    "VJ_UNCOMP" },
  46.   { PROTO_VJCOMP,    "VJ_COMP" },
  47.   { PROTO_COMPD,    "COMPD" },
  48.   { PROTO_LCP,        "LCP" },
  49.   { PROTO_IPCP,        "IPCP" },
  50.   { PROTO_CCP,        "CCP" },
  51.   { PROTO_PAP,        "PAP" },
  52.   { PROTO_LQR,        "LQR" },
  53.   { PROTO_CHAP,        "CHAP" },
  54.   { 0,            "Others" },
  55. };
  56.  
  57. static u_short fcstab[256] = {
  58. /* 00 */    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  59. /* 08 */    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  60. /* 10 */    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  61. /* 18 */    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  62. /* 20 */    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  63. /* 28 */    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  64. /* 30 */    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  65. /* 38 */    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  66. /* 40 */    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  67. /* 48 */    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  68. /* 50 */    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  69. /* 58 */    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  70. /* 60 */    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  71. /* 68 */    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  72. /* 70 */    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  73. /* 78 */    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  74. /* 80 */    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  75. /* 88 */    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  76. /* 90 */    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  77. /* 98 */    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  78. /* a0 */    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  79. /* a8 */    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  80. /* b0 */    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  81. /* b8 */    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  82. /* c0 */    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  83. /* c8 */    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  84. /* d0 */    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  85. /* d8 */    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  86. /* e0 */    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  87. /* e8 */    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  88. /* f0 */    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  89. /* f8 */    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  90. };
  91.  
  92. void
  93. HdlcInit()
  94. {
  95.   ifInOctets = ifOutOctets = 0;
  96.   ifInPackets = ifOutPackets = 0;
  97.   ifOutLQRs = 0;
  98. }
  99.  
  100. /*
  101.  *  HDLC FCS computation. Read RFC 1171 Appendix B and CCITT X.25 section
  102.  *  2.27 for further details.
  103.  */
  104. u_short
  105. HdlcFcs(fcs, cp, len)
  106. u_short fcs;
  107. u_char *cp;
  108. int len;
  109. {
  110.   while (len--)
  111.     fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
  112.   return(fcs);
  113. }
  114.  
  115. void
  116. HdlcOutput(int pri, u_short proto, struct mbuf *bp)
  117. {
  118.   struct mbuf *mhp, *mfcs;
  119.   struct protostat *statp;
  120.   struct lqrdata *lqr;
  121.   u_char *cp;
  122.   u_short fcs;
  123.  
  124.   if ((proto & 0xfff1) == 0x21) {    /* Network Layer protocol */
  125.     if (CcpFsm.state == ST_OPENED) {
  126.       Pred1Output(pri, proto, bp);
  127.       return;
  128.     }
  129.   }
  130.   mfcs = mballoc(2, MB_HDLCOUT);
  131.   mhp = mballoc(4, MB_HDLCOUT);
  132.   mhp->cnt = 0;
  133.   cp = MBUF_CTOP(mhp);
  134.   if (proto == PROTO_LCP || LcpInfo.his_acfcomp == 0) {
  135.     *cp++ = HDLC_ADDR;
  136.     *cp++ = HDLC_UI;
  137.     mhp->cnt += 2;
  138.   }
  139.   /*
  140.    *  If possible, compress protocol field.
  141.    */
  142.   if (LcpInfo.his_protocomp && (proto & 0xff00) == 0) {
  143.     *cp++ = proto;
  144.     mhp->cnt++;
  145.   } else {
  146.     *cp++ = proto >> 8;
  147.     *cp = proto & 0377;
  148.     mhp->cnt += 2;
  149.   }
  150.   mhp->next = bp;
  151.   bp->next = mfcs;
  152.  
  153.   lqr = &MyLqrData;
  154.   lqr->PeerOutPackets = ifOutPackets++;
  155.   ifOutOctets += plength(mhp) + 1;
  156.   lqr->PeerOutOctets = ifOutOctets;
  157.  
  158.   if (proto == PROTO_LQR) {
  159.     lqr->MagicNumber = LcpInfo.want_magic;
  160.     lqr->LastOutLQRs = HisLqrData.PeerOutLQRs;
  161.     lqr->LastOutPackets = HisLqrData.PeerOutPackets;
  162.     lqr->LastOutOctets = HisLqrData.PeerOutOctets;
  163.     lqr->PeerInLQRs = HisLqrSave.SaveInLQRs;
  164.     lqr->PeerInPackets = HisLqrSave.SaveInPackets;
  165.     lqr->PeerInDiscards = HisLqrSave.SaveInDiscards;
  166.     lqr->PeerInErrors = HisLqrSave.SaveInErrors;
  167.     lqr->PeerInOctets = HisLqrSave.SaveInOctets;
  168.     lqr->PeerOutLQRs = ++ifOutLQRs;
  169.     LqrDump("LqrOutput", lqr);
  170.     LqrChangeOrder(lqr, (struct lqrdata *)(MBUF_CTOP(bp)));
  171.   }
  172.  
  173.   fcs = HdlcFcs(INITFCS, MBUF_CTOP(mhp), mhp->cnt);
  174.   fcs = HdlcFcs(fcs, MBUF_CTOP(bp), bp->cnt);
  175.   fcs = ~fcs;
  176.   cp = MBUF_CTOP(mfcs);
  177.   *cp++ = fcs & 0377;    /* Low byte first!! */
  178.   *cp++ = fcs >> 8;
  179.  
  180.   LogDumpBp(LOG_HDLC, "HdlcOutput", mhp);
  181.   for (statp = ProtocolStat; statp->number; statp++)
  182.     if (statp->number == proto)
  183.       break;
  184.   statp->out_count++;
  185.   AsyncOutput(pri, mhp, proto);
  186. }
  187.  
  188. DecodePacket(proto, bp)
  189. u_short proto;
  190. struct mbuf *bp;
  191. {
  192. #ifdef DEBUG
  193.   logprintf("proto = %04x\n", proto);
  194. #endif
  195.   switch (proto) {
  196.   case PROTO_LCP:
  197.     LcpInput(bp);
  198.     break;
  199.   case PROTO_PAP:
  200.     PapInput(bp);
  201.     break;
  202.   case PROTO_LQR:
  203.     HisLqrSave.SaveInLQRs++;
  204.     LqrInput(bp);
  205.     break;
  206.   case PROTO_CHAP:
  207.     ChapInput(bp);
  208.     break;
  209.   case PROTO_VJUNCOMP:
  210.   case PROTO_VJCOMP:
  211.     bp = VjCompInput(bp, proto);
  212.     /* fall down */
  213.   case PROTO_IP:
  214.     IpInput(bp);
  215.     break;
  216.   case PROTO_IPCP:
  217.     IpcpInput(bp);
  218.     break;
  219.   case PROTO_CCP:
  220.     CcpInput(bp);
  221.     break;
  222.   case PROTO_COMPD:
  223.     Pred1Input(bp);
  224.     break;
  225.   default:
  226.     logprintf("Unknown protocol 0x%04x\n", proto);
  227.     /*
  228.      * XXX: Should send protocol reject.
  229.      */
  230.     HisLqrSave.SaveInDiscards++;
  231.     HdlcStat.unknownproto++;
  232.     pfree(bp);
  233.     break;
  234.   }
  235. }
  236.  
  237. int
  238. ReportProtStatus()
  239. {
  240.   struct protostat *statp;
  241.   int cnt;
  242.  
  243.   statp = ProtocolStat;
  244.   statp--;
  245.   cnt = 0;
  246.   printf("    Protocol     in        out      Protocol      in       out\n");
  247.   do {
  248.     statp++;
  249.     printf("   %-9s: %8u, %8u",
  250.       statp->name, statp->in_count, statp->out_count);
  251.     if (++cnt == 2) {
  252.       printf("\n");
  253.       cnt = 0;
  254.     }
  255.   } while (statp->number);
  256.   if (cnt)
  257.      printf("\n");
  258.   return(1);
  259. }
  260.  
  261. int
  262. ReportHdlcStatus()
  263. {
  264.   struct hdlcstat *hp = &HdlcStat;
  265.  
  266.   printf("HDLC level errors\n\n");
  267.   printf("FCS: %u  ADDR: %u  COMMAND: %u  PROTO: %u\n",
  268.     hp->badfcs, hp->badaddr, hp->badcommand, hp->unknownproto);
  269.   return(1);
  270. }
  271.  
  272. static struct hdlcstat laststat;
  273.  
  274. void
  275. HdlcErrorCheck()
  276. {
  277.   struct hdlcstat *hp = &HdlcStat;
  278.   struct hdlcstat *op = &laststat;
  279.  
  280.   if (bcmp(hp, op, sizeof(laststat))) {
  281.     LogPrintf(LOG_PHASE, "HDLC errros -> FCS: %u ADDR: %u COMD: %u PROTO: %u\n",
  282.     hp->badfcs - op->badfcs, hp->badaddr - op->badaddr,
  283.     hp->badcommand - op->badcommand, hp->unknownproto - op->unknownproto);
  284.   }
  285.   laststat = HdlcStat;
  286. }
  287.  
  288. void
  289. HdlcInput(struct mbuf *bp)
  290. {
  291.   u_short fcs, proto;
  292.   u_char *cp, addr, ctrl;
  293.   struct protostat *statp;
  294.  
  295.   LogDumpBp(LOG_HDLC, "HdlcInput:", bp);
  296.   fcs = HdlcFcs(INITFCS, MBUF_CTOP(bp), bp->cnt);
  297.   HisLqrSave.SaveInOctets += bp->cnt + 1;
  298.  
  299. #ifdef DEBUG
  300.   logprintf("fcs = %04x (%s)\n", fcs, (fcs == GOODFCS)? "good" : "bad");
  301. #endif
  302.   if (fcs != GOODFCS) {
  303.     HisLqrSave.SaveInErrors++;
  304. #ifdef DEBUG
  305.     logprintf("Bad FCS\n");
  306. #endif
  307.     HdlcStat.badfcs++;
  308.     pfree(bp);
  309.     return;
  310.   }
  311.   bp->cnt -= 2;        /* discard FCS part */
  312.   cp = MBUF_CTOP(bp);
  313.  
  314.   ifInPackets++;
  315.   ifInOctets += bp->cnt;
  316.  
  317.   if (!LcpInfo.want_acfcomp) {
  318.     /*
  319.      *  We expect that packet is not compressed.
  320.      */
  321.     addr = *cp++;
  322.     if (addr != HDLC_ADDR) {
  323.       HisLqrSave.SaveInErrors++;
  324.       HdlcStat.badaddr++;
  325. #ifdef DEBUG
  326.       logprintf("addr %02x\n", *cp);
  327. #endif
  328.       pfree(bp);
  329.       return;
  330.     }
  331.  
  332.     ctrl = *cp++;
  333.     if (ctrl != HDLC_UI) {
  334.       HisLqrSave.SaveInErrors++;
  335.       HdlcStat.badcommand++;
  336. #ifdef DEBUG
  337.       logprintf("command %02x\n", *cp);
  338. #endif
  339.       pfree(bp);
  340.       return;
  341.     }
  342.     bp->offset += 2;
  343.     bp->cnt -= 2;
  344.   } else if (cp[0] == HDLC_ADDR && cp[1] == HDLC_UI) {
  345.     /*
  346.      *  We can receive compressed packet, but peer still send
  347.      *  uncompressed packet to me.
  348.      */
  349.     cp += 2;
  350.     bp->offset += 2;
  351.     bp->cnt -= 2;
  352.   }
  353.  
  354.   if (LcpInfo.want_protocomp) {
  355.     proto = 0;
  356.     cp--;
  357.     do {
  358.       cp++; bp->offset++; bp->cnt--;
  359.       proto = proto << 8;
  360.       proto += *cp;
  361.     } while (!(proto & 1));
  362.   } else {
  363.     proto = *cp++ << 8;
  364.     proto |= *cp++;
  365.     bp->offset += 2;
  366.     bp->cnt -= 2;
  367.   }
  368.  
  369.   for (statp = ProtocolStat; statp->number; statp++)
  370.     if (statp->number == proto)
  371.       break;
  372.   statp->in_count++;
  373.   HisLqrSave.SaveInPackets++;
  374.  
  375.   DecodePacket(proto, bp);
  376. }
  377.